package antlr.c;

import org.antlr.v4.runtime.CharStreams;
import org.antlr.v4.runtime.CommonTokenStream;

import java.util.ArrayDeque;
import java.util.Deque;
import java.util.HashMap;
import java.util.Map;

public class Interpreter extends SimpleCBaseVisitor<Integer> {
    private Map<String, SimpleCParser.FunctionDeclarationContext> functions = new HashMap<>();
    private Map<String, Integer> variables = new HashMap<>();
    private Deque<Map<String, Integer>> callStack = new ArrayDeque<>();

    public static void main(String[] args) {
        String sourceCode = "int add(int a, int b) {\n" +
                "int result;\n" +
                "result = a + b;\n" +
                "return result;\n" +
                "}\n" +
                "\n" +
                "int main() {\n" +
                "int x;\n" +
                "x = add(3, 4);\n" +
                "return x ;\n" +
                "}";


        // 解析源代码
        SimpleCLexer lexer = new SimpleCLexer(CharStreams.fromString(sourceCode));
        SimpleCParser parser = new SimpleCParser(new CommonTokenStream(lexer));
        SimpleCParser.CompilationUnitContext program = parser.compilationUnit();

        // 解释执行
        Interpreter interpreter = new Interpreter();
        interpreter.visit(program);
    }


    @Override
    public Integer visitFunctionDeclaration(SimpleCParser.FunctionDeclarationContext ctx) {
        String name = ctx.ID().getText();
        functions.put(name, ctx);
        return null;
    }

    @Override
    public Integer visitVariableDeclaration(SimpleCParser.VariableDeclarationContext ctx) {
        String name = ctx.ID().getText();
        variables.put(name, 0);
        return null;
    }

    @Override
    public Integer visitAssignment(SimpleCParser.AssignmentContext ctx) {
        String name = ctx.ID().getText();
        int value = visit(ctx.expr());
        variables.put(name, value);
        return null;
    }

    @Override
    public Integer visitFunctionCall(SimpleCParser.FunctionCallContext ctx) {
        String name = ctx.ID().getText();
        SimpleCParser.FunctionDeclarationContext function = functions.get(name);
        callStack.push(new HashMap<>(variables));
        for (int i = 0; i < function.parameterList().parameter().size(); i++) {
            String paramName = function.parameterList().parameter(i).ID().getText();
            int argValue = visit(ctx.argumentList().expr(i));
            variables.put(paramName, argValue);
        }
        visit(function.compoundStatement());
        int result = variables.get("result");
        variables = callStack.pop();
        return result;
    }

    // ...其他的visit方法...
}
